package com.cloud.service.file.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cloud.domain.file.Folder;
import com.cloud.domain.sys.FolderConfig;
import com.cloud.mapper.file.FolderMapper;
import com.cloud.param.file.FolderParam;
import com.cloud.param.file.ResourceParam;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloud.service.file.FolderService;
import com.cloud.service.sys.FolderConfigService;
import com.cloud.type.file.FileStatus;
import com.cloud.type.file.FileType;
import com.cloud.type.file.SizeType;
import com.cloud.type.sys.StorageType;
import com.common.utils.tools.result.ServiceResult;
import com.common.utils.tools.system.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.*;

import static com.common.utils.tools.files.FileSizeUtil.*;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liuyuan
 * @since 2019-09-23
 */
@Service
public class FolderServiceImpl extends ServiceImpl<FolderMapper, Folder> implements FolderService {
    protected static Logger logger = LoggerFactory.getLogger(FolderServiceImpl.class);

    @Autowired
    FolderMapper folderMapper;
    @Autowired
    FolderConfigService folderConfigService;


    @Override
    @Transactional
    public Boolean mkdirFolder(Folder fromFolder) {
        String userName = fromFolder.getUserName();
        logger.info("-------------->userName:" + userName);
        FolderConfig folderConfig = folderConfigService.getPathConfig(StorageType.USER);
        String path = "";
        String mkdirType = "";
        String rootPath = "";
        String system = SystemUtils.getCurrentOperatingSystem();
        if (system.contains("linux")) {
            rootPath = folderConfig.getLinuxUrl() + StorageType.USER.name().toLowerCase();
        } else if (system.contains("mac")) {
            rootPath = folderConfig.getMacUrl();
        } else {

        }
        if ("MD5".equals(mkdirType)) {

        } else {
            /**
             *
             * id 为null 为父级目录
             * id 不为null 为父级id
             * */
            logger.info("-------------->getParentId:" + fromFolder.getParentId());
            logger.info("-------------->fileName:" + fromFolder.getName());

            if (fromFolder.getParentId() == null || fromFolder.getParentId() == 0) {
                //路径
                path = rootPath + "/" + userName + "/" + fromFolder.getName();
                fromFolder.setParentId(0L);
                fromFolder.setType(FileType.FOLDER);
                fromFolder.setStatus(FileStatus.ACTIVE);
                fromFolder.setPath(path);
            } else if (fromFolder.getParentId() != null) {
                Folder folderModel = this.getById(fromFolder.getParentId());
                path = folderModel.getPath() + "/" + fromFolder.getName();
                fromFolder.setParentId(fromFolder.getParentId());
                fromFolder.setPath(path);
                fromFolder.setType(FileType.FOLDER);
                fromFolder.setStatus(FileStatus.ACTIVE);
            }
        }
        java.io.File file = new java.io.File(path);
        try {
            // 判断文件父目录是否存在
            if (!file.getParentFile().exists()) {
                boolean mkdirs = file.getParentFile().mkdirs();
                if (mkdirs) {
                    return this.save(fromFolder);
                }
            } else {
                boolean mkdir = file.mkdir();
                if (mkdir) {
                    return this.save(fromFolder);
                }
            }


        } catch (Exception e) {
            e.printStackTrace();
        }


        return false;

    }

    @Override
    @Transactional
    public Boolean rename(Folder fromFolder) {
        Folder folderModel = this.getById(fromFolder.getId());
        String nowName = fromFolder.getName();
        String oldName = folderModel.getName();
        FileType type = folderModel.getType();
        if(FileType.FOLDER.equals(type)){

           /* String oldPath = folderModel.getPath();
            String nowPath = oldPath.replace(oldName, nowName);
            java.io.File oldFile = new java.io.File(oldPath);
            java.io.File nowFile = new java.io.File(nowPath);
            boolean updateFile = oldFile.renameTo(nowFile);
            if (updateFile) {
                folderModel.setName(nowName);
                folderModel.setPath(nowPath);
                boolean updateFolder = this.updateById(folderModel);
                return updateFolder;
            }*/
           return null;
        }else {
            String fileName = fromFolder.getFileName();
            String nowFileName = fileName+"."+folderModel.getType().getCode();
            String oldFileName = folderModel.getFileName();
            String path = folderModel.getPath();
            String oldOpenPath = folderModel.getOpenPath();
            String nowOpenPath = oldOpenPath.replace(oldFileName, nowFileName);
            String newFilePath = path +"/"+nowFileName;
            String oldFilePath = path +"/"+oldFileName;
            File oldFile = new File(oldFilePath);
            File nowFile = new File(newFilePath);
            boolean up = oldFile.renameTo(nowFile);
            if(up){
                folderModel.setFileName(nowFileName);
                folderModel.setOpenPath(nowOpenPath);
                return this.updateById(folderModel);
            }

        }
        return false;
    }

    @Override
    @Transactional
    public Boolean deleteFile(Long id) {
        Folder folderModel = this.getById(id);
        String name = folderModel.getName();
        //如果是文件夹将删除文件以及文件
        String path = folderModel.getPath();
        java.io.File file = new java.io.File(path);
        if (name != null) {
            Boolean res = delFile(file);
            if (res) {
                Collection<Long> deleteFileId = getDeleteFileId(folderModel.getId());
                int count = folderMapper.deleteBatchIds(deleteFileId);
                System.out.println("用户" + folderModel.getUserName() + "删除了:" + count + "文件以及数据");
                return true;
            }
        } else {
            String fileName = folderModel.getFileName();
            String deleteSingletonFile = path + "/" + fileName;
            File delFile = new File(deleteSingletonFile);
            boolean delete = delFile.delete();
            if (delete) {
                int count = folderMapper.deleteById(id);
                if (count == 1) {
                    return true;
                } else {
                    return false;
                }
            }

        }
        return null;
    }

    @Override
    public ServiceResult upload(ResourceParam resourceParam) {
        FolderConfig folderConfig = folderConfigService.getPathConfig(StorageType.USER);
        try {
            String rootPath = null;
            String system = SystemUtils.getCurrentOperatingSystem();
            if (system.contains("linux")) {
                rootPath = folderConfig.getLinuxUrl() + StorageType.USER.name().toLowerCase();
            } else if (system.contains("mac")) {
                rootPath = folderConfig.getMacUrl();
            } else {

            }
            String path;
            Long parentId = null;
            String openPath;
            if (resourceParam.getFileId() == null || resourceParam.getFileId() == 0) {
                path = rootPath + "/" + resourceParam.getUserName() + "/";
                openPath = resourceParam.getUserName() + "/";
                parentId = 0L;
            } else {
                Folder folderModel = this.getById(resourceParam.getFileId());
                parentId = folderModel.getId();
                path = folderModel.getPath();
                String[] splitPath = path.split(resourceParam.getUserName());
                String lastPath = splitPath[splitPath.length - 1];
                openPath = resourceParam.getUserName() + "/" + lastPath + "/";

            }
            MultipartFile[] files = resourceParam.getFiles();
            for (MultipartFile file : files) {
                String originalFilename = file.getOriginalFilename();
                Folder folderModel = getByFileName(parentId,file.getOriginalFilename());
                if(folderModel != null){
                    return ServiceResult.ok(false,"文件夹已存在");
                }
                //logger.info("原始文件名称："+originalFilename);
                String type = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
                //logger.info("文件类型：" + type);
                String realPath = path + "/" + originalFilename;
                long size = file.getSize();
                double fileOrFilesSize = getFileOrFilesSize(size, SIZETYPE_MB);
                String openUrl = folderConfig.getOpenGateway() + openPath + originalFilename;
                java.io.File dest = new java.io.File(realPath);
                file.transferTo(dest);
                Folder createFolder = new Folder();
                createFolder.setParentId(parentId);
                createFolder.setSize(fileOrFilesSize);
                createFolder.setUserId(resourceParam.getUserId());
                createFolder.setPath(path);
                createFolder.setOpenPath(openUrl);
                createFolder.setSizeType(SizeType.MB);
                createFolder.setUserName(resourceParam.getUserName());
                createFolder.setFileName(originalFilename);
                FileType fileType = FileType.toEnum(type);
                createFolder.setType(fileType);
                createFolder.setStatus(FileStatus.ACTIVE);
                this.save(createFolder);
            }
            return ServiceResult.ok(true,"上传成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return  ServiceResult.ok(false,"上传失败");
    }

    private Folder getByFileName(Long parentId, String originalFilename) {
        Folder folder = new Folder();
        folder.setParentId(parentId);
        folder.setFileName(originalFilename);
        QueryWrapper<Folder> queryWrapper = new QueryWrapper<>(folder);
        return this.getOne(queryWrapper);
    }

    @Override
    public IPage<Folder> listChildrenFileByPage(FolderParam folderParam) {

        if (folderParam.getParentId() == null) {
            folderParam.setParentId(0L);
        } else {
            folderParam.setParentId(folderParam.getParentId());
        }
        QueryWrapper<Folder> queryWrapper = new QueryWrapper<>(folderParam);
        queryWrapper.orderByDesc("create_date");
        Page<Folder> folderPage = new Page<>(folderParam.getPageNo(), folderParam.getPageSize());
        return this.page(folderPage, queryWrapper);
    }

    @Override
    public IPage<Folder> getParentFolderByPage(FolderParam folderParam) {
        folderParam.setId(null);
        QueryWrapper<Folder> queryWrapper = new QueryWrapper<>(folderParam);
        queryWrapper.orderByDesc("create_date");
        Page<Folder> folderPage = new Page<>(folderParam.getPageNo(), folderParam.getPageSize());
        return this.page(folderPage, queryWrapper);
    }

    public boolean delFile(java.io.File file) {
        if (file.isDirectory()) {
            java.io.File[] files = file.listFiles();
            for (java.io.File f : files) {
                delFile(f);
            }
        }
        return file.delete();
    }

    public Collection<Long> getDeleteFileId(Long id) {
        Collection<Long> listId = new ArrayList<>();
        listId.add(id);
        Collection<Folder> childrenFolders = getChildrenFile(id);
        for (Folder childrenFolder : childrenFolders) {
            listId.add(childrenFolder.getId());
            this.getDeleteFileId(childrenFolder.getId());
        }
        return listId;

    }


    public Collection<Folder> getChildrenFile(Long id) {
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("parent_id", id);
        Collection<Folder> folders = this.listByMap(queryMap);
        return folders;
    }

    public static void main(String[] args) {

    }

}
